package com.bsj.power.pls.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.path.PathSearchDTO;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.entity.job.WorkPersonnel;
import com.bsj.power.common.def.entity.locationDevice.LocationDevice;
import com.bsj.power.common.def.entity.path.Path;
import com.bsj.power.common.def.entity.path.PathDevice;
import com.bsj.power.common.def.entity.pathReport.PathReport;
import com.bsj.power.common.def.entity.personnel.Personnel;
import com.bsj.power.common.def.vo.pls.FormsPathVO;
import com.bsj.power.common.def.vo.pls.PathReportCountVO;
import com.bsj.power.common.def.vo.pls.PathReportVO;
import com.bsj.power.common.mapper.*;
import com.bsj.power.common.util.DateUtils;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.power.pls.service.PathReportService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description PathReportServiceImpl
 * @time 2024/5/7 11:52
 */
@Service
public class PathReportServiceImpl implements PathReportService {

    @Resource
    private PathReportMapper pathReportMapper;

    @Resource
    private PathMapper pathMapper;

    @Resource
    private WorkPersonnelMapper workPersonnelMapper;

    @Resource
    private PersonnelMapper personnelMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private PathDeviceMapper pathDeviceMapper;

    @Resource
    private LocationDeviceMapper locationDeviceMapper;

    /**
     * 区域进出统计报表
     *
     * @param pathSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.PathReportCountVO>>
     * @author ljx
     * @time 2024/5/7 14:46
     */
    @Override
    public JsonResult<List<PathReportCountVO>> pagePathReportCount(PathSearchDTO pathSearchDTO) {
        long total = pathReportMapper.countPathReport(pathSearchDTO);
        if (total == NumericalConstants.ZERO) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        pathSearchDTO.initPageNumber();
        return JsonResult.success(pathReportMapper.pagePathReportCount(pathSearchDTO), total);
    }

    /**
     * 获取区域进出报表
     *
     * @param dto
     * @return
     */
    @Override
    public JsonResult<List<PathReportCountVO>> pagePathReport(PathSearchDTO dto) {
        IPage<PathReport> page = new Page<>(dto.getPageNumber(), dto.getPageSize());
        QueryWrapper<PathReport> queryWrapper = new QueryWrapper<>();
        if (dto.getStartTime() != null && dto.getEndTime() != null) {
            queryWrapper.lambda().between(PathReport::getCreateTime, dto.getStartTime(), dto.getEndTime());
        }
        if (dto.getDeviceName() != null) {
            queryWrapper.lambda().like(PathReport::getDeviceName, dto.getDeviceName());
        }
        if (dto.getPathId() != null) {
            queryWrapper.lambda().eq(PathReport::getPathId, dto.getPathId());
        }
        //根据人员名称查询
        String personnelName = dto.getPersonnelName();
        if (personnelName != null) {
            List<String> empNoList = new ArrayList<>();
            //有可能是作业人员,也有可能是负责人
            List<WorkPersonnel> workPersonnelList = workPersonnelMapper.selectList(Wrappers.<WorkPersonnel>lambdaQuery()
                    .eq(WorkPersonnel::getName, personnelName));
            List<Personnel> personnelList = personnelMapper.selectList(Wrappers.<Personnel>lambdaQuery()
                    .eq(Personnel::getName, personnelName));
            if (CollectionUtils.isEmpty(workPersonnelList)
                    && CollectionUtils.isEmpty(personnelList)) {
                return JsonResult.success();
            }
            if (workPersonnelList != null) {
                workPersonnelList.stream().forEach(wp -> {
                    empNoList.add(wp.getTemporaryEmpNo());
                });
            }
            if (personnelList != null) {
                personnelList.stream().forEach(pl -> {
                    empNoList.add(pl.getEmpNo());
                });
            }
            if (!empNoList.isEmpty()) {
                queryWrapper.lambda().in(PathReport::getEmpNo, empNoList);
            }
        }
        queryWrapper.lambda().orderByDesc(PathReport::getCreateTime);
        IPage<PathReport> iPage = pathReportMapper.selectPage(page, queryWrapper);
        List<PathReport> records = iPage.getRecords();
        if (records.isEmpty()) {
            return JsonResult.success();
        }
        //结果集合
        List<PathReportCountVO> result = new ArrayList<>();
        List<String> deviceNameList = records.stream().map(PathReport::getDeviceName).collect(Collectors.toList());
        //查询定位设备信息
        List<LocationDevice> locationDevices = locationDeviceMapper.selectList(Wrappers.<LocationDevice>lambdaQuery()
                .in(LocationDevice::getDeviceName, deviceNameList));
        Map<String, LocationDevice> devMap = locationDevices.stream().collect(Collectors.toMap(LocationDevice::getDeviceName, Function.identity()));
        records.stream().forEach(item -> {
            Path path = pathMapper.selectById(item.getPathId());
            List<Device> devices = new ArrayList<>();
            if (path != null) {
                //围栏关联国标设备ID
                List<PathDevice> pathDevices = pathDeviceMapper.selectList(Wrappers.<PathDevice>lambdaQuery()
                        .eq(PathDevice::getPathId, path.getPathId()));
                //国标设备集合
                if (!CollectionUtils.isEmpty(pathDevices)) {
                    devices = deviceMapper.selectBatchIds(pathDevices.stream()
                            .map(PathDevice::getDeviceId).collect(Collectors.toList()));
                }
            }
            LocationDevice locationDevice = devMap.get(item.getDeviceName());
            PathReportCountVO vo = PathReportCountVO.builder()
                    .createTime(DateUtils.dateToStr(item.getCreateTime()))
                    .deviceName(item.getDeviceName())
                    .nikeName(locationDevice == null ? "" : locationDevice.getNikeName())
                    .type(item.getType())
                    .pathName(path == null ? "" : path.getPathName())
                    .deviceList(devices)
                    .build();
            Integer personnelType = item.getPersonnelType();
            Integer personnelId = item.getPersonnelId();
            if (personnelType == 1) {
                //负责人
                Personnel personnel = personnelMapper.selectById(personnelId);
                if (personnel != null) {
                    vo.setPersonnelName(personnel.getName());
                    vo.setEmpNo(personnel.getEmpNo());
                }
            } else if (personnelType == 2) {
                //作业人员
                WorkPersonnel workPersonnel = workPersonnelMapper.selectById(personnelId);
                if (workPersonnel != null) {
                    vo.setPersonnelName(workPersonnel.getName());
                    vo.setEmpNo(workPersonnel.getTemporaryEmpNo());
                }
            }
            result.add(vo);
        });
        return JsonResult.success(result, iPage.getTotal());
    }

    /**
     * 区域进出报表
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     */
    @Override
    public JsonResult<List<FormsPathVO>> formsReport(String startTime, String endTime) {
        Date start = DateUtils.nDaysAgo(LocalDateTime.now(), 6);
        Date end = new Date();
        if (startTime != null && endTime != null) {
            start = DateUtils.strToDate(startTime);
            end = DateUtils.strToDate(endTime);
        }
        List<PathReport> pathReports = pathReportMapper.selectList(Wrappers.<PathReport>lambdaQuery()
                .between(PathReport::getCreateTime, start, end).isNotNull(PathReport::getPathName));
        Map<String, List<PathReport>> countList = pathReports.stream().collect(Collectors.groupingBy(PathReport::getPathName));
        List<FormsPathVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(countList)) {
            countList.entrySet().forEach(entry -> {
                List<PathReport> value = entry.getValue();
                //再根据进出类型统计数量
                Map<Integer, List<PathReport>> typeMap = value.stream().collect(Collectors.groupingBy(PathReport::getType));
                Map<String, Long> countMap = new HashMap<>();
                typeMap.forEach((k, v) -> {
                    countMap.put(k + "", (long) v.size());
                });
                FormsPathVO formsPathVO = FormsPathVO.builder()
                        .pathName(entry.getKey())
                        .countMap(countMap)
                        .build();
                result.add(formsPathVO);
            });
        }
        return JsonResult.success(result);
    }

    /**
     * 区域进出详情
     *
     * @param pathSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.pls.PathReportVO>>
     * @author ljx
     * @time 2024/5/7 19:21
     */
    @Override
    public JsonResult<List<PathReportVO>> pathReportDetail(PathSearchDTO pathSearchDTO) {
        ParamCheckUtil.isBlank(pathSearchDTO.getPathName());
        long total = pathReportMapper.countPathReportDetail(pathSearchDTO);
        if (total == NumericalConstants.ZERO) {
            return JsonResult.success(new ArrayList<>(), total);
        }
        pathSearchDTO.initPageNumber();
        return JsonResult.success(pathReportMapper.pathReportDetail(pathSearchDTO), total);
    }
}
